GH-148 Implement mentions system with @player detection and sound notifications#208
GH-148 Implement mentions system with @player detection and sound notifications#208
Conversation
Co-authored-by: Jakubk15 <77227023+Jakubk15@users.noreply.github.com>
Co-authored-by: Jakubk15 <77227023+Jakubk15@users.noreply.github.com>
Co-authored-by: Jakubk15 <77227023+Jakubk15@users.noreply.github.com>
Co-authored-by: Jakubk15 <77227023+Jakubk15@users.noreply.github.com>
# Conflicts: # build.gradle.kts # buildSrc/build.gradle.kts # chatformatter-paper-plugin/build.gradle.kts # gradle/wrapper/gradle-wrapper.properties
2026-02-07.14-04-35.mp4 |
|
this PR is bundled also with:
|
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request introduces a well-structured player mention system with sound notifications. The separation of core logic, configuration, and the Paper-specific implementation is clean, and the inclusion of unit tests for the detection logic is a great practice.
However, there are a few discrepancies between the pull request description and the implemented code that should be addressed:
- The
/chatformatter mentiontogglecommand and the associated per-player settings (mention-settings.yml,enabledByDefaultconfig) are mentioned as part of this PR but have not been implemented. The command handler has been refactored to support subcommands, which is a good step, but only thereloadcommand is present. - The filtering of self-mentions was also mentioned but is missing from the implementation. I've added a specific comment with a suggestion to fix this.
Overall, this is a solid foundation for the mentions feature. Addressing the missing pieces will bring it in line with the described functionality.
chatformatter-core/src/main/java/com/eternalcode/formatter/ChatHandlerImpl.java
Outdated
Show resolved
Hide resolved
chatformatter-core/src/main/java/com/eternalcode/formatter/mention/MentionDetector.java
Outdated
Show resolved
Hide resolved
…tion/MentionDetector.java Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
633bc02 to
94f4b86
Compare
94f4b86 to
5ac4ff7
Compare
| import java.util.Map; | ||
| import java.util.Optional; | ||
|
|
||
| import static net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection; |
| List<Player> players = detectMentions(message); | ||
| Sound sound = loadSound(); | ||
|
|
||
| for (Player player : players) { | ||
| player.playSound(player.getLocation(), sound, config.mentions.volume, config.mentions.pitch); | ||
| } | ||
| } | ||
|
|
||
| private List<Player> detectMentions(String message) { | ||
| if (!this.config.mentions.enabled) { | ||
| return List.of(); | ||
| } |
There was a problem hiding this comment.
| List<Player> players = detectMentions(message); | |
| Sound sound = loadSound(); | |
| for (Player player : players) { | |
| player.playSound(player.getLocation(), sound, config.mentions.volume, config.mentions.pitch); | |
| } | |
| } | |
| private List<Player> detectMentions(String message) { | |
| if (!this.config.mentions.enabled) { | |
| return List.of(); | |
| } | |
| if (!this.config.mentions.enabled) { | |
| return List.of(); | |
| } | |
| List<Player> players = detectMentions(message); | |
| Sound sound = loadSound(); | |
| for (Player player : players) { | |
| player.playSound(player.getLocation(), sound, config.mentions.volume, config.mentions.pitch); | |
| } | |
| } | |
| private List<Player> detectMentions(String message) { |
| } | ||
|
|
||
| void mentionPlayers(String message) { | ||
| List<Player> players = detectMentions(message); |
There was a problem hiding this comment.
| List<Player> players = detectMentions(message); | |
| List<Player> mentionedPlayers = detectMentions(message); |
CitralFlo
left a comment
There was a problem hiding this comment.
Few suggestions:
- Add support for mentions without
@-> meaning entering a username in chat would ping the user - Make username mention configurable - so users can add hover or change the color of mentions in chat
Possible alternative:
- Use packetEvents to support suggestions when user enters
@in chat - Move matcher logic to process only messages containing the
@xxx- less work for the Service
| @Contextual | ||
| public class MentionConfig implements Serializable { | ||
|
|
||
| @Description({ " ", "# Mention system configuration" }) |
There was a problem hiding this comment.
| @Description({ " ", "# Mention system configuration" }) | |
| @Description("# Mention system configuration") |
| @Description("# When a player mentions another player with @playername, the mentioned player will hear a sound") | ||
| public boolean enabled = true; | ||
|
|
||
| @Description({ " ", "# The sound to play when a player is mentioned" }) |
There was a problem hiding this comment.
| @Description({ " ", "# The sound to play when a player is mentioned" }) | |
| @Description("# The sound to play when a player is mentioned") |
| @Description("# Available sounds: https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/Sound.html") | ||
| public String sound = "BLOCK_NOTE_BLOCK_PLING"; | ||
|
|
||
| @Description({ " ", "# The volume of the mention sound (0.0 to 1.0)" }) |
There was a problem hiding this comment.
| @Description({ " ", "# The volume of the mention sound (0.0 to 1.0)" }) | |
| @Description("# The volume of the mention sound (0.0 to 1.0)") |
| @Description({ " ", "# The volume of the mention sound (0.0 to 1.0)" }) | ||
| public float volume = 1.0f; | ||
|
|
||
| @Description({ " ", "# The pitch of the mention sound (0.5 to 2.0)" }) |
There was a problem hiding this comment.
| @Description({ " ", "# The pitch of the mention sound (0.5 to 2.0)" }) | |
| @Description("# The pitch of the mention sound (0.5 to 2.0)") |
|
|
||
| @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR) | ||
| void onMention(AsyncPlayerChatEvent event) { | ||
| mentionService.mentionPlayers(event.getMessage()); |
There was a problem hiding this comment.
| mentionService.mentionPlayers(event.getMessage()); | |
| this.mentionService.mentionPlayers(event.getMessage()); |
|
|
||
|
|
|
|
||
| // Mentions | ||
| this.mentionService = new MentionService(server, pluginConfig); | ||
| server.getPluginManager().registerEvents(new MentionListener(mentionService), plugin); | ||
|
|
||
| // Update checker | ||
| server.getPluginManager().registerEvents(new UpdaterController(updaterService, pluginConfig, audienceProvider, miniMessage), plugin); |
There was a problem hiding this comment.
Comments prbly not needed here
Adds player mentions via
@playernamesyntax with configurable sound notifications and per-player toggle controls.Architecture
Core (
chatformatter-core)MentionDetector- Regex-based detection of@[a-zA-Z0-9_]{3,16}patterns, returns online players onlyMentionService- Coordinates detectionMentionConfig- Config schema for sound type, volume, pitch, and default stateChatRenderedMessagerecord withList<Player> mentionedPlayersfieldChatHandlerImpl.process()to detect mentions from raw message textPaper Integration (
chatformatter-paper-plugin)MentionSoundHandler- Plays configured sound to mentioned playersPaperChatEventExecutorto trigger sounds whenmentionedPlayersis non-emptyCommands
ChatFormatterCommandwith switch expression pattern for subcommandsConfiguration
Usage
Testing
Warning
Firewall rules blocked me from connecting to one or more addresses (expand for details)
I tried to connect to the following addresses, but was blocked by firewall rules:
hub.spigotmc.org/usr/lib/jvm/temurin-17-jdk-amd64/bin/java /usr/lib/jvm/temurin-17-jdk-amd64/bin/java --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.lang.invoke=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.prefs/java.util.prefs=ALL-UNNAMED --add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED --add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.prefs/java.util.prefs=ALL-UNNAMED --add-opens=java.base/java.nio.charset=ALL-UNNAMED --add-opens=java.base/java.net=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED --add-opens=java.xml/javax.xml.namespace=ALL-UNNAMED --add-opens=java.base/java.time=ALL-UNNAMED -XX:MaxMetaspaceSize=384m -XX:+HeapDumpOnOutOfMemoryError -Xms256m -Xmx512m -Dfile.encoding=UTF-8(dns block)If you need me to access, download, or install something from one of these locations, you can either:
Original prompt
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.